package com.kifas.controller;

import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import javax.xml.bind.JAXBElement;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.kifas.entity.GroupEntity;
import com.kifas.entity.UserEntity;
import com.kifas.model.xml.GroupModel;
import com.kifas.model.xml.LoginValidationModel;
import com.kifas.model.xml.PersistStatus;
import com.kifas.model.xml.UserModel;
import com.kifas.service.EntityServiceManager;

@Component
@Scope("prototype")
@Path("/Users")
public class UserController {

	private static Logger log = Logger.getLogger(UserController.class);

	@Context
	UriInfo uriInfo;

	@Autowired
	private EntityServiceManager entityManager;

	@POST
	@Produces(MediaType.APPLICATION_XML)
	@Consumes(MediaType.APPLICATION_XML)
	public PersistStatus insert(JAXBElement<UserModel> xml) {
		UserModel model = xml.getValue();
		try {
			UserEntity user = new UserEntity(model.getUsername(), model.getPassword(), model.getFirstName(), model.getLastName(), model.getEmail(),
					model.getCreatedBy());
			entityManager.persist(user);
		} catch (Exception e) {
			log.error("can not persist user", e);
			return new PersistStatus("UserEntity", "failed", "can not persist user entity");
		}
		return new PersistStatus("UserEntity", "success");
	}

	@POST
	@Path("Group")
	@Produces
	public PersistStatus addGroup(JAXBElement<UserModel> xml) {
		UserModel model = xml.getValue();
		try {
			UserEntity user = entityManager.getUser(model.getUsername());
			List<GroupEntity> groups = new ArrayList<GroupEntity>();
			for (GroupModel groupModel : model.getGroups()) {
				groups.add(entityManager.getGroupById(groupModel.getIdGroup()));
			}
			user.setGroups(groups);
			entityManager.update(user);
		} catch (Exception e) {
			log.error("can not update user to group", e);
			return new PersistStatus("UserEntity", "failed", "can not update user to group");
		}
		return new PersistStatus("UserEntity", "success");
	}

	@POST
	@Path("Login")
	@Produces(MediaType.APPLICATION_XML)
	public LoginValidationModel validate(String username, String password) {
		LoginValidationModel model = new LoginValidationModel();
		model.setUsername(username);
		model.setPassword(password);
		model.setValid(entityManager.getUserValidation(username, password));
		return model;
	}

	@PUT
	@Consumes(MediaType.APPLICATION_XML)
	@Produces(MediaType.APPLICATION_XML)
	public PersistStatus update(JAXBElement<UserModel> xml) {
		UserModel model = xml.getValue();
		UserEntity user = new UserEntity(model.getUsername(), model.getPassword(), model.getFirstName(), model.getLastName(), model.getEmail(),
				model.getCreatedBy());
		try {
			entityManager.update(user);
		} catch (Exception e) {
			return new PersistStatus("UserEntity", "failed", "can not update user");
		}
		return new PersistStatus("UserEntity", "success");
	}

	@GET
	@Produces(MediaType.APPLICATION_XML)
	public List<UserModel> getAllUSers() {
		return transformList(entityManager.getUsers());
	}

	@GET
	@Path("{username}")
	@Produces(MediaType.APPLICATION_XML)
	public UserModel getUserByUsername(@PathParam("username") String username) {
		return transform(entityManager.getUser(username));
	}

	private UserModel transform(UserEntity user) {
		UserModel model = new UserModel(user.getUsername(), user.getSecretCode(), user.getFirstName(), user.getLastName(), user.getEmail(), user.getCreatedBy());
		List<GroupModel> groupModels = new ArrayList<GroupModel>();
		for (GroupEntity group : user.getGroups()) {
			GroupModel groupModel = new GroupModel(group.getIdGroup(), group.getName(), group.isEnable());
			groupModels.add(groupModel);
		}
		model.setGroups(groupModels);
		return model;
	}

	private List<UserModel> transformList(List<UserEntity> users) {
		List<UserModel> userModels = new ArrayList<UserModel>();
		for (UserEntity user : users) {
			userModels.add(transform(user));
		}
		return userModels;
	}
}
